#ifndef METHOD_JS
#define METHOD_JS

#include "Concept.js"
#include "Patterns.js"
#include "AccessModifier.js"

/* class */ Method = function(/* Concept */ concept)
{
	if (!(concept instanceof Concept))
	{
		throw "ArgumentException";
	}
	
	var _accessModifier;
	var _isStatic;
	var _name;
	var _signature;
	var _body;
	
	(function()
	{
		var captures = Method.RegExp.exec(concept.Head);
		
		if (captures == null)
		{
			throw "BadConceptException";
		}
		
		_isStatic = captures[Method.StaticPosition];
		
		switch (captures[Method.AccessModifierPosition])
		{
			case "public":
				_accessModifier = AccessModifier.Public;
				break;
			case "protected":
				if (_isStatic)
				{
					throw "A static method cannot be protected.";
				}
				
				_accessModifier = AccessModifier.Protected;
				break;
			case "private":
			case undefined:
				_accessModifier = AccessModifier.Private;
				break;
		}
		
		_name = captures[Method.NamePosition];
		_signature = captures[Method.SignaturePosition];
		if (_signature == undefined)
		{
			_signature = "";
		}
		_body = concept.Body;
	})();
	
	this.__defineGetter__("AccessModifier", function() { return _accessModifier; });
	this.__defineSetter__("AccessModifier", function() { throw "MethodAccessibilityException"; });
	
	this.__defineGetter__("IsStatic", function() { return _isStatic; });
	this.__defineSetter__("IsStatic", function() { throw "MethodAccessibilityException"; });
	
	this.__defineGetter__("Name", function() { return _name; });
	this.__defineSetter__("Name", function() { throw "MethodAccessibilityException"; });
	
	this.__defineGetter__("Signature", function() { return _signature; });
	this.__defineSetter__("Signature", function() { throw "MethodAccessibilityException"; });
	
	this.__defineGetter__("Body", function() { return _body; });
	this.__defineSetter__("Body", function() { throw "MethodAccessibilityException"; });
	
	this.ToNonStaticJs = function()
	{
		if (_isStatic)
		{
			throw "InvalidOperationException";
		}
		
		var output = "";
		
		output += "var " + _name + "=function(" + _signature + "){" + _body + "};";
		
		if (_accessModifier == AccessModifier.Public)
		{
			output += "this." + _name + "=" + _name + ";";
		}
		
		return output;
	};
	
	this.ToPrivateStaticJs = function()
	{
		if (!_isStatic)
		{
			throw "InvalidOperationException";
		}
		
		return "var " + _name + "=function(" + _signature + "){" + _body + "};";
	};
	
	this.ToPublicStaticJs = function(/* string */ className)
	{
		if (!_isStatic)
		{
			throw "InvalidOperationException";
		}
		
		var output = "";
		
		if (_accessModifier == AccessModifier.Public)
		{
			output += className + "." + _name + "=" + _name + ";";
		}
		
		return output;
	};
};

/* static bool */ Method.IsMatching = function(/* Concept */ concept)
{
	if (!(concept instanceof Concept))
	{
		throw "ArgumentException";
	}
	
	return Method.RegExp.test(concept.Head);
};

(function()
{
	var _pattern = "^(" + Patterns.AccessModifier + "[ ])?(static[ ])?" + Patterns.Identifier + "\\(" + Patterns.Signature + "\\)$";
	
	var _regExp = new RegExp(_pattern);
	Method.__defineGetter__("RegExp", function() { return _regExp; });
	Method.__defineSetter__("RegExp", function() { throw "MethodAccessibilityException"; });
	
	var _accessModifierPosition = 2;
	Method.__defineGetter__("AccessModifierPosition", function() { return _accessModifierPosition; });
	Method.__defineSetter__("AccessModifierPosition", function() { throw "MethodAccessibilityException"; });	
	
	var _staticPosition = 3;
	Method.__defineGetter__("StaticPosition", function() { return _staticPosition; });
	Method.__defineSetter__("StaticPosition", function() { throw "MethodAccessibilityException"; });
	
	var _namePosition = 4;
	Method.__defineGetter__("NamePosition", function() { return _namePosition; });
	Method.__defineSetter__("NamePosition", function() { throw "MethodAccessibilityException"; });
	
	var _signaturePosition = 5;
	Method.__defineGetter__("SignaturePosition", function() { return _signaturePosition; });
	Method.__defineSetter__("SignaturePosition", function() { throw "MethodAccessibilityException"; });
})();

#endif
